Allow non-privileged domains restricted access to
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Sat, 31 Dec 2005 13:15:22 +0000 (14:15 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Sat, 31 Dec 2005 13:15:22 +0000 (14:15 +0100)
I/O memory and physical interrupts, under control
of domain0. Capabilities are maintained as rangesets
in Xen.

Signed-off-by: Ryan Wilson <hap9@epoch.ncsc.mil>
Signed-off-by: Keir Fraser <keir@xensource.com>
23 files changed:
tools/libxc/xc_domain.c
tools/libxc/xenctrl.h
tools/python/xen/lowlevel/xc/xc.c
xen/arch/ia64/xen/domain.c
xen/arch/ia64/xen/irq.c
xen/arch/x86/dom0_ops.c
xen/arch/x86/domain_build.c
xen/arch/x86/irq.c
xen/arch/x86/mm.c
xen/arch/x86/physdev.c
xen/arch/x86/traps.c
xen/common/dom0_ops.c
xen/common/domain.c
xen/common/event_channel.c
xen/common/memory.c
xen/common/rangeset.c
xen/drivers/char/ns16550.c
xen/include/asm-x86/iocap.h
xen/include/public/dom0_ops.h
xen/include/xen/compiler.h
xen/include/xen/iocap.h
xen/include/xen/rangeset.h
xen/include/xen/sched.h

index fe3cf556189a594f9902b66069864f9175047a7d..b018318d62758104b1820f9c638ccb7de2778ba3 100644 (file)
@@ -404,6 +404,38 @@ int xc_domain_setinfo(int xc_handle,
 
 }
 
+int xc_domain_irq_permission(int xc_handle,
+                             uint32_t domid,
+                             uint8_t pirq,
+                             uint8_t allow_access)
+{
+    dom0_op_t op;
+
+    op.cmd = DOM0_IRQ_PERMISSION;
+    op.u.irq_permission.domain = domid;
+    op.u.irq_permission.pirq = pirq;
+    op.u.irq_permission.allow_access = allow_access;
+
+    return do_dom0_op(xc_handle, &op);
+}
+
+int xc_domain_iomem_permission(int xc_handle,
+                               uint32_t domid,
+                               unsigned long first_pfn,
+                               unsigned long nr_pfns,
+                               uint8_t allow_access)
+{
+    dom0_op_t op;
+
+    op.cmd = DOM0_IOMEM_PERMISSION;
+    op.u.iomem_permission.domain = domid;
+    op.u.iomem_permission.first_pfn = first_pfn;
+       op.u.iomem_permission.nr_pfns = nr_pfns;
+    op.u.iomem_permission.allow_access = allow_access;
+
+    return do_dom0_op(xc_handle, &op);
+}
+
 /*
  * Local variables:
  * mode: C
index 6700bd1c0d813be1d335e47fea8f842e08f69b0f..f558b5985ea068920656449475fb1650c0f9f116 100644 (file)
@@ -380,6 +380,17 @@ int xc_domain_ioport_permission(int xc_handle,
                                 uint32_t nr_ports,
                                 uint32_t allow_access);
 
+int xc_domain_irq_permission(int xc_handle,
+                             uint32_t domid,
+                             uint8_t pirq,
+                             uint8_t allow_access);
+
+int xc_domain_iomem_permission(int xc_handle,
+                               uint32_t domid,
+                               unsigned long first_pfn,
+                               unsigned long nr_pfns,
+                               uint8_t allow_access);
+
 unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid, 
                                    unsigned long mfn);
 
index 95b0a9f101428ca72dd02a8c1566560fb129e247..30f0ef6d819526adba2f377609dcf7041dfe2f3f 100644 (file)
@@ -774,6 +774,52 @@ static PyObject *pyxc_domain_ioport_permission(XcObject *self,
     return zero;
 }
 
+static PyObject *pyxc_domain_irq_permission(PyObject *self,
+                                            PyObject *args,
+                                            PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    uint32_t dom;
+    int pirq, allow_access, ret;
+
+    static char *kwd_list[] = { "dom", "pirq", "allow_access", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iii", kwd_list, 
+                                      &dom, &pirq, &allow_access) )
+        return NULL;
+
+    ret = xc_domain_irq_permission(
+        xc->xc_handle, dom, pirq, allow_access);
+    if ( ret != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    Py_INCREF(zero);
+    return zero;
+}
+
+static PyObject *pyxc_domain_iomem_permission(PyObject *self,
+                                               PyObject *args,
+                                               PyObject *kwds)
+{
+    XcObject *xc = (XcObject *)self;
+    uint32_t dom;
+    unsigned long first_pfn, nr_pfns, allow_access, ret;
+
+    static char *kwd_list[] = { "dom", "first_pfn", "nr_pfns", "allow_access", NULL };
+
+    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "illi", kwd_list, 
+                                      &dom, &first_pfn, &nr_pfns, &allow_access) )
+        return NULL;
+
+    ret = xc_domain_iomem_permission(
+        xc->xc_handle, dom, first_pfn, nr_pfns, allow_access);
+    if ( ret != 0 )
+        return PyErr_SetFromErrno(xc_error);
+
+    Py_INCREF(zero);
+    return zero;
+}
+
 
 static PyObject *dom_op(XcObject *self, PyObject *args,
                         int (*fn)(int, uint32_t))
@@ -1070,6 +1116,25 @@ static PyMethodDef pyxc_methods[] = {
       " allow_access [int]: Non-zero means enable access; else disable access\n\n"
       "Returns: [int] 0 on success; -1 on error.\n" },
 
+    { "domain_irq_permission",
+      (PyCFunction)pyxc_domain_irq_permission,
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Allow a domain access to a physical IRQ\n"
+      " dom          [int]: Identifier of domain to be allowed access.\n"
+      " pirq         [int]: The Physical IRQ\n"
+      " allow_access [int]: Non-zero means enable access; else disable access\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
+    { "domain_iomem_permission",
+      (PyCFunction)pyxc_domain_iomem_permission,
+      METH_VARARGS | METH_KEYWORDS, "\n"
+      "Allow a domain access to a range of IO memory pages\n"
+      " dom          [int]: Identifier of domain to be allowed access.\n"
+      " first_pfn   [long]: First page of I/O Memory\n"
+      " nr_pfns     [long]: Number of pages of I/O Memory (>0)\n"
+      " allow_access [int]: Non-zero means enable access; else disable access\n\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
     { "pages_to_kib",
       (PyCFunction)pyxc_pages_to_kib,
       METH_VARARGS, "\n"
index 5b68519bbe45ec451d3c8e847487b223203455d9..b784372cd889c4de55fd9ea7a08974c89b9448a0 100644 (file)
@@ -765,7 +765,10 @@ void alloc_dom0(void)
  */
 void physdev_init_dom0(struct domain *d)
 {
-       set_bit(_DOMF_physdev_access, &d->domain_flags);
+       if (iomem_permit_access(d, 0UL, ~0UL))
+               BUG();
+       if (irqs_permit_access(d, 0, NR_PIRQS-1))
+               BUG();
 }
 
 unsigned int vmx_dom0 = 0;
index b694d62bc91dc20b5a981f50d34fda829ce40bdc..1537873e042cb32d0a6f75aa455bcaf3ab9968c8 100644 (file)
@@ -1378,9 +1378,6 @@ int pirq_guest_bind(struct vcpu *d, int irq, int will_share)
     unsigned long       flags;
     int                 rc = 0;
 
-    if ( !IS_CAPABLE_PHYSDEV(d->domain) )
-        return -EPERM;
-
     spin_lock_irqsave(&desc->lock, flags);
 
     action = (irq_guest_action_t *)desc->action;
index 022fa33e3528f9ac24fc57dd28cc56688f247101..5a4f493ce0da517a69727e410225cee923a02edc 100644 (file)
@@ -152,14 +152,12 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
             op->u.ioport_permission.domain)) == NULL) )
             break;
 
-        ret = 0;
-        if ( np > 0 )
-        {
-            if ( op->u.ioport_permission.allow_access )
-                ioport_range_permit(d, fp, fp + np - 1);
-            else
-                ioport_range_deny(d, fp, fp + np - 1);
-        }
+        if ( np == 0 )
+            ret = 0;
+        else if ( op->u.ioport_permission.allow_access )
+            ret = ioports_permit_access(d, fp, fp + np - 1);
+        else
+            ret = ioports_deny_access(d, fp, fp + np - 1);
 
         put_domain(d);
     }
index cdeb08265c4a00e37003713abe18468e88dd1522..d08f2c12fb0d6ceccda79d9f7eb0fb2588867645 100644 (file)
@@ -94,7 +94,7 @@ static struct pfn_info *alloc_chunk(struct domain *d, unsigned long max_pages)
     return page;
 }
 
-static void process_dom0_ioports_disable()
+static void process_dom0_ioports_disable(void)
 {
     unsigned long io_from, io_to;
     char *t, *u, *s = opt_dom0_ioports_disable;
@@ -126,7 +126,8 @@ static void process_dom0_ioports_disable()
         printk("Disabling dom0 access to ioport range %04lx-%04lx\n",
             io_from, io_to);
 
-        ioport_range_deny(dom0, io_from, io_to);
+        if ( ioports_deny_access(dom0, io_from, io_to) != 0 )
+            BUG();
     }
 }
 
@@ -741,24 +742,29 @@ int construct_dom0(struct domain *d,
         printk("dom0: shadow setup done\n");
     }
 
+    i = 0;
+
     /* DOM0 is permitted full I/O capabilities. */
-    ioport_range_permit(dom0, 0, 0xFFFF);
-    set_bit(_DOMF_physdev_access, &dom0->domain_flags);
+    i |= ioports_permit_access(dom0, 0, 0xFFFF);
+    i |= iomem_permit_access(dom0, 0UL, ~0UL);
+    i |= irqs_permit_access(dom0, 0, NR_PIRQS-1);
 
     /*
      * Modify I/O port access permissions.
      */
     /* Master Interrupt Controller (PIC). */
-    ioport_range_deny(dom0, 0x20, 0x21);
+    i |= ioports_deny_access(dom0, 0x20, 0x21);
     /* Slave Interrupt Controller (PIC). */
-    ioport_range_deny(dom0, 0xA0, 0xA1);
+    i |= ioports_deny_access(dom0, 0xA0, 0xA1);
     /* Interval Timer (PIT). */
-    ioport_range_deny(dom0, 0x40, 0x43);
+    i |= ioports_deny_access(dom0, 0x40, 0x43);
     /* PIT Channel 2 / PC Speaker Control. */
-    ioport_range_deny(dom0, 0x61, 0x61);
+    i |= ioports_deny_access(dom0, 0x61, 0x61);
     /* Command-line I/O ranges. */
     process_dom0_ioports_disable();
 
+    BUG_ON(i != 0);
+
     return 0;
 }
 
index e0553486bc5668cc6096e83b19351a10f0a2b7e7..a1aee360c3b43942f751c07f162cfea7b7dcc15c 100644 (file)
@@ -199,16 +199,12 @@ int pirq_guest_unmask(struct domain *d)
 int pirq_guest_bind(struct vcpu *v, int irq, int will_share)
 {
     unsigned int        vector = irq_to_vector(irq);
-    struct domain      *d = v->domain;
     irq_desc_t         *desc = &irq_desc[vector];
     irq_guest_action_t *action;
     unsigned long       flags;
     int                 rc = 0;
     cpumask_t           cpumask = CPU_MASK_NONE;
 
-    if ( !IS_CAPABLE_PHYSDEV(d) )
-        return -EPERM;
-
     if ( vector == 0 )
         return -EBUSY;
 
index e6a99065e3a3604fef205fd55daa6a9588bc02c1..683c4b75348a2d3b9f4312cdfe611052880b5c8b 100644 (file)
@@ -96,6 +96,7 @@
 #include <xen/softirq.h>
 #include <xen/domain_page.h>
 #include <xen/event.h>
+#include <xen/iocap.h>
 #include <asm/shadow.h>
 #include <asm/page.h>
 #include <asm/flushtlb.h>
@@ -437,7 +438,6 @@ get_page_from_l1e(
     unsigned long mfn = l1e_get_pfn(l1e);
     struct pfn_info *page = pfn_to_page(mfn);
     int okay;
-    extern int domain_iomem_in_pfn(struct domain *d, unsigned long pfn);
 
     if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
         return 1;
@@ -455,8 +455,7 @@ get_page_from_l1e(
         if ( d == dom_io )
             d = current->domain;
 
-        if ( (!IS_PRIV(d)) &&
-             (!IS_CAPABLE_PHYSDEV(d) || !domain_iomem_in_pfn(d, mfn)) )
+        if ( !iomem_access_permitted(d, mfn, mfn) )
         {
             MEM_LOG("Non-privileged attempt to map I/O space %08lx", mfn);
             return 0;
@@ -1887,7 +1886,7 @@ int do_mmuext_op(
             break;
 
         case MMUEXT_FLUSH_CACHE:
-            if ( unlikely(!IS_CAPABLE_PHYSDEV(d)) )
+            if ( unlikely(!cache_flush_permitted(d)) )
             {
                 MEM_LOG("Non-physdev domain tried to FLUSH_CACHE.");
                 okay = 0;
index 0e7c1c10c50bdfad81cef1444108b111dd3f262b..e8cb5b8707a7d11909517ccf6ec03d86a5146c23 100644 (file)
 extern int ioapic_guest_read(int apicid, int address, u32 *pval);
 extern int ioapic_guest_write(int apicid, int address, u32 pval);
 
-/* Check if a domain controls a device with IO memory within frame @pfn.
- * Returns: 1 if the domain should be allowed to map @pfn, 0 otherwise.  */
-int domain_iomem_in_pfn(struct domain *p, unsigned long pfn)
-{
-    return 0;
-}
-
 /*
  * Demuxing hypercall.
  */
index 8216452fd013f335ab96e9b53e73e09f2eb25897..a4be3db3b3852ec482a0dcf0ea9d1cc4415fe878 100644 (file)
@@ -623,7 +623,7 @@ static inline int admin_io_okay(
     unsigned int port, unsigned int bytes,
     struct vcpu *v, struct cpu_user_regs *regs)
 {
-    return ioport_range_access_permitted(v->domain, port, port + bytes - 1);
+    return ioports_access_permitted(v->domain, port, port + bytes - 1);
 }
 
 /* Check admin limits. Silently fail the access if it is disallowed. */
@@ -863,7 +863,7 @@ static int emulate_privileged_op(struct cpu_user_regs *regs)
 
     case 0x09: /* WBINVD */
         /* Ignore the instruction if unprivileged. */
-        if ( !IS_CAPABLE_PHYSDEV(v->domain) )
+        if ( !cache_flush_permitted(v->domain) )
             DPRINTK("Non-physdev domain attempted WBINVD.\n");
         else
             wbinvd();
index a4cbc48b4ff8f407e557cb447e0d1dd93c440f83..97cd5713769beac0ce4a45529d8ee275f9f95cb3 100644 (file)
@@ -16,6 +16,7 @@
 #include <xen/domain_page.h>
 #include <xen/trace.h>
 #include <xen/console.h>
+#include <xen/iocap.h>
 #include <asm/current.h>
 #include <public/dom0_ops.h>
 #include <public/sched_ctl.h>
@@ -582,6 +583,7 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
         }
     }
     break;
+
     case DOM0_SETDEBUGGING:
     {
         struct domain *d; 
@@ -599,6 +601,53 @@ long do_dom0_op(dom0_op_t *u_dom0_op)
     }
     break;
 
+    case DOM0_IRQ_PERMISSION:
+    {
+        struct domain *d;
+        unsigned int pirq = op->u.irq_permission.pirq;
+
+        ret = -EINVAL;
+        if ( pirq >= NR_PIRQS )
+            break;
+
+        ret = -ESRCH;
+        d = find_domain_by_id(op->u.irq_permission.domain);
+        if ( d == NULL )
+            break;
+
+        if ( op->u.irq_permission.allow_access )
+            ret = irq_permit_access(d, pirq);
+        else
+            ret = irq_deny_access(d, pirq);
+
+        put_domain(d);
+    }
+    break;
+
+    case DOM0_IOMEM_PERMISSION:
+    {
+        struct domain *d;
+        unsigned long pfn = op->u.iomem_permission.first_pfn;
+        unsigned long nr_pfns = op->u.iomem_permission.nr_pfns;
+
+        ret = -EINVAL;
+        if ( (pfn + nr_pfns - 1) < pfn ) /* wrap? */
+            break;
+
+        ret = -ESRCH;
+        d = find_domain_by_id(op->u.iomem_permission.domain);
+        if ( d == NULL )
+            break;
+
+        if ( op->u.iomem_permission.allow_access )
+            ret = iomem_permit_access(d, pfn, pfn + nr_pfns - 1);
+        else
+            ret = iomem_deny_access(d, pfn, pfn + nr_pfns - 1);
+
+        put_domain(d);
+    }
+    break;
+
 #ifdef PERF_COUNTERS
     case DOM0_PERFCCONTROL:
     {
index 46f45950b2fce6cda2f8b39a479bf4ff0fa178fb..0f206d8e1c298a94e372871ff874a6c457ffd856 100644 (file)
@@ -60,7 +60,12 @@ struct domain *do_createdomain(domid_t dom_id, unsigned int cpu)
 
     rangeset_domain_initialise(d);
 
-    if ( arch_do_createdomain(v) != 0 )
+    d->iomem_caps = rangeset_new(d, "I/O Memory", RANGESETF_prettyprint_hex);
+    d->irq_caps   = rangeset_new(d, "Interrupts", 0);
+
+    if ( (d->iomem_caps == NULL) ||
+         (d->irq_caps == NULL) ||
+         (arch_do_createdomain(v) != 0) )
         goto fail3;
 
     if ( !is_idle_task(d) )
index eeccc0e1602f5e2926b06c21a7cb08cb9564523e..fdda1e86b8c2c32ceaab6499c43be61e10111a9d 100644 (file)
@@ -22,6 +22,7 @@
 #include <xen/sched.h>
 #include <xen/event.h>
 #include <xen/irq.h>
+#include <xen/iocap.h>
 #include <asm/current.h>
 
 #include <public/xen.h>
@@ -242,6 +243,9 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind)
     if ( pirq >= ARRAY_SIZE(d->pirq_to_evtchn) )
         return -EINVAL;
 
+    if ( !irq_access_permitted(d, pirq) )
+        return -EPERM;
+
     spin_lock(&d->evtchn_lock);
 
     if ( d->pirq_to_evtchn[pirq] != 0 )
index 45934fdf762060e35debb25e04e56f3915bd1b04..847fcbb0cc6935065088b2f9bda3ebee7e3c0111 100644 (file)
@@ -15,6 +15,7 @@
 #include <xen/sched.h>
 #include <xen/event.h>
 #include <xen/shadow.h>
+#include <xen/iocap.h>
 #include <asm/current.h>
 #include <asm/hardirq.h>
 #include <public/memory.h>
@@ -35,7 +36,8 @@ increase_reservation(
          !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
         return 0;
 
-    if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current->domain) )
+    if ( (extent_order != 0) &&
+         !multipage_allocation_permitted(current->domain) )
     {
         DPRINTK("Only I/O-capable domains may allocate multi-page extents.\n");
         return 0;
index a1680a29f2cc337a0194ba802cc07b9ab6b8178b..de17a90ec566636cd412a7de2c50a9f86ee052b2 100644 (file)
@@ -253,6 +253,12 @@ int rangeset_contains_singleton(
     return rangeset_contains_range(r, s, s);
 }
 
+int rangeset_is_empty(
+    struct rangeset *r)
+{
+    return list_empty(&r->range_list);
+}
+
 struct rangeset *rangeset_new(
     struct domain *d, char *name, unsigned int flags)
 {
index 6784983b3ba566837b970d8cabbaeea33327ad30..8ef838d3dbc14e76d6eb2db001712fd5f7dc51ac 100644 (file)
@@ -237,7 +237,8 @@ static void ns16550_init_postirq(struct serial_port *port)
 static void ns16550_endboot(struct serial_port *port)
 {
     struct ns16550 *uart = port->uart;
-    ioport_range_deny(dom0, uart->io_base, uart->io_base + 7);
+    if ( ioports_deny_access(dom0, uart->io_base, uart->io_base + 7) != 0 )
+        BUG();
 }
 #else
 #define ns16550_endboot NULL
index e60b82ff3a2195c495883a0264f21423dacde358..c7463cb6f280fa3becc263ae3c3b1289380c1798 100644 (file)
@@ -7,11 +7,14 @@
 #ifndef __X86_IOCAP_H__
 #define __X86_IOCAP_H__
 
-#define ioport_range_permit(d, s, e)                    \
+#define ioports_permit_access(d, s, e)                  \
     rangeset_add_range((d)->arch.ioport_caps, s, e)
-#define ioport_range_deny(d, s, e)                      \
+#define ioports_deny_access(d, s, e)                    \
     rangeset_remove_range((d)->arch.ioport_caps, s, e)
-#define ioport_range_access_permitted(d, s, e)          \
+#define ioports_access_permitted(d, s, e)               \
     rangeset_contains_range((d)->arch.ioport_caps, s, e)
 
+#define cache_flush_permitted(d)                       \
+    (!rangeset_is_empty((d)->iomem_caps))
+
 #endif /* __X86_IOCAP_H__ */
index b6b5914200c02c2a7f0f44aa3559e5a4e940650a..a2c66be1f482f35ff86b85de3080e112fddb5c81 100644 (file)
@@ -410,6 +410,21 @@ typedef struct {
     uint8_t enable;
 } dom0_setdebugging_t;
 
+#define DOM0_IRQ_PERMISSION 46
+typedef struct {
+    domid_t domain;          /* domain to be affected */
+    uint8_t pirq;
+    uint8_t allow_access;    /* flag to specify enable/disable of IRQ access */
+} dom0_irq_permission_t;
+
+#define DOM0_IOMEM_PERMISSION 47
+typedef struct {
+    domid_t  domain;          /* domain to be affected */
+    unsigned long first_pfn;  /* first page (physical page number) in range */
+    unsigned long nr_pfns;    /* number of pages in range (>0) */
+    uint8_t allow_access;     /* allow (!0) or deny (0) access to range? */
+} dom0_iomem_permission_t;
 typedef struct {
     uint32_t cmd;
     uint32_t interface_version; /* DOM0_INTERFACE_VERSION */
@@ -448,6 +463,8 @@ typedef struct {
         dom0_max_vcpus_t         max_vcpus;
         dom0_setdomainhandle_t   setdomainhandle;        
         dom0_setdebugging_t      setdebugging;
+        dom0_irq_permission_t    irq_permission;
+        dom0_iomem_permission_t  iomem_permission;
         uint8_t                  pad[128];
     } u;
 } dom0_op_t;
index f0c5fbf17ab743f9357a4bf2b1da01509bb059b0..29acdc59e8c3bcf5125cf9bc075da4bf43345000 100644 (file)
 #define __attribute_used__ __attribute__((__unused__))
 #endif
 
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#define __must_check __attribute__((warn_unused_result))
+#else
+#define __must_check
+#endif
+
 #endif /* __LINUX_COMPILER_H */
index 967f70fe4ba08b8061200661f8575aab097139fe..db461b9dcb0fa97eb4c1478c83bd5472dbfbf45b 100644 (file)
 #include <xen/rangeset.h>
 #include <asm/iocap.h>
 
+#define iomem_permit_access(d, s, e)                    \
+    rangeset_add_range((d)->iomem_caps, s, e)
+#define iomem_deny_access(d, s, e)                      \
+    rangeset_remove_range((d)->iomem_caps, s, e)
+#define iomem_access_permitted(d, s, e)                 \
+    rangeset_contains_range((d)->iomem_caps, s, e)
+
+#define irq_permit_access(d, i)                         \
+    rangeset_add_singleton((d)->irq_caps, i)
+#define irq_deny_access(d, i)                           \
+    rangeset_remove_singleton((d)->irq_caps, i)
+#define irqs_permit_access(d, s, e)                     \
+    rangeset_add_range((d)->irq_caps, s, e)
+#define irqs_deny_access(d, s, e)                       \
+    rangeset_remove_range((d)->irq_caps, s, e)
+#define irq_access_permitted(d, i)                      \
+    rangeset_contains_singleton((d)->irq_caps, i)
+
+#define multipage_allocation_permitted(d)               \
+    (!rangeset_is_empty((d)->iomem_caps))
+
 #endif /* __XEN_IOCAP_H__ */
index ffd14ad17d2e871d2e73ded48270de2f6880dd0d..d4a8e00393a4423b9095f9d2c858fe8e63e0ebd7 100644 (file)
@@ -43,20 +43,23 @@ void rangeset_destroy(
 #define _RANGESETF_prettyprint_hex 0
 #define RANGESETF_prettyprint_hex  (1U << _RANGESETF_prettyprint_hex)
 
+int __must_check rangeset_is_empty(
+    struct rangeset *r);
+
 /* Add/remove/query a numeric range. */
-int rangeset_add_range(
+int __must_check rangeset_add_range(
     struct rangeset *r, unsigned long s, unsigned long e);
-int rangeset_remove_range(
+int __must_check rangeset_remove_range(
     struct rangeset *r, unsigned long s, unsigned long e);
-int rangeset_contains_range(
+int __must_check rangeset_contains_range(
     struct rangeset *r, unsigned long s, unsigned long e);
 
 /* Add/remove/query a single number. */
-int rangeset_add_singleton(
+int __must_check rangeset_add_singleton(
     struct rangeset *r, unsigned long s);
-int rangeset_remove_singleton(
+int __must_check rangeset_remove_singleton(
     struct rangeset *r, unsigned long s);
-int rangeset_contains_singleton(
+int __must_check rangeset_contains_singleton(
     struct rangeset *r, unsigned long s);
 
 /* Rangeset pretty printing. */
index 4bc824741a54072ee4cb715a7e22c1d789f598be..c686394b7f350112d3d96ae85d9f9da2aa2f2294 100644 (file)
@@ -11,6 +11,7 @@
 #include <xen/time.h>
 #include <xen/ac_timer.h>
 #include <xen/grant_table.h>
+#include <xen/rangeset.h>
 #include <asm/domain.h>
 
 extern unsigned long volatile jiffies;
@@ -128,6 +129,10 @@ struct domain
     u16              pirq_to_evtchn[NR_PIRQS];
     u32              pirq_mask[NR_PIRQS/32];
 
+    /* I/O capabilities (access to IRQs and memory-mapped I/O). */
+    struct rangeset *iomem_caps;
+    struct rangeset *irq_caps;
+
     unsigned long    domain_flags;
     unsigned long    vm_assist;
 
@@ -381,23 +386,20 @@ extern struct domain *domain_list;
  /* Is this domain privileged? */
 #define _DOMF_privileged       1
 #define DOMF_privileged        (1UL<<_DOMF_privileged)
- /* May this domain do IO to physical devices? */
-#define _DOMF_physdev_access   2
-#define DOMF_physdev_access    (1UL<<_DOMF_physdev_access)
  /* Guest shut itself down for some reason. */
-#define _DOMF_shutdown         3
+#define _DOMF_shutdown         2
 #define DOMF_shutdown          (1UL<<_DOMF_shutdown)
  /* Guest is in process of shutting itself down (becomes DOMF_shutdown). */
-#define _DOMF_shuttingdown     4
+#define _DOMF_shuttingdown     3
 #define DOMF_shuttingdown      (1UL<<_DOMF_shuttingdown)
  /* Death rattle. */
-#define _DOMF_dying            5
+#define _DOMF_dying            4
 #define DOMF_dying             (1UL<<_DOMF_dying)
  /* Domain is paused by controller software. */
-#define _DOMF_ctrl_pause       6
+#define _DOMF_ctrl_pause       5
 #define DOMF_ctrl_pause        (1UL<<_DOMF_ctrl_pause)
  /* Domain is being debugged by controller software. */
-#define _DOMF_debugging        7
+#define _DOMF_debugging        6
 #define DOMF_debugging         (1UL<<_DOMF_debugging)
 
 
@@ -425,8 +427,6 @@ static inline void vcpu_unblock(struct vcpu *v)
 
 #define IS_PRIV(_d)                                         \
     (test_bit(_DOMF_privileged, &(_d)->domain_flags))
-#define IS_CAPABLE_PHYSDEV(_d)                              \
-    (test_bit(_DOMF_physdev_access, &(_d)->domain_flags))
 
 #define VM_ASSIST(_d,_t) (test_bit((_t), &(_d)->vm_assist))